import get from 'lodash-es/get.js';
import vueGlobal from '@gis/lib/vueGlobal.js';

const config = {
  messageKey: 'message_unique_key_' + Date.now(),
  isResponseSuccess: (res) => res && String(res.code).trim() === '200',
  handleSuccessMessage: ({ content, key }) => {
    vueGlobal.get('$message.success', 'function', (message) => {
      message({ content, key });
    });
  },
  handleErrorMessage: ({ content, key }) => {
    vueGlobal.get('$message.error', 'function', (message) => {
      message({ content, key });
    });
  },
};

function tryToParseJson(str, defaultValue) {
  if (typeof str !== 'string') {
    return str;
  }
  try {
    const data = JSON.parse(str);
    return typeof data === 'object' && data ? data : defaultValue;
  } catch (error) {
    return str || defaultValue; // 返回的data为字符串
  }
}

export function configResolver(option) {
  Object.assign(config, {}, option);
}

export const BASE_OPTION = {
  errMsg: '获取数据失败',
  okMsg: null,
  onOk: null,
  onFail: null,
  silent: null,
  useResMsg: null,
};
export const COMMON_OPTION = {
  dataKey: 'data',
  totalKey: 'data.count',
  pageKey: 'data.page_number',
  defaultValue: [],
};
export const FORM_OPTION = {
  baseText: '操作',
  okText: '成功',
  failText: '失败',
};
export const TABLE_OPTION = {
  dataKey: 'data.list',
  totalKey: 'data.count',
  pageKey: 'data.page_number',
  pageSizeKey: 'data.page_size',
  defaultValue: [],
};

function getMsg(useResMsg, resMsg, defaultMsg) {
  if (useResMsg !== false) {
    return resMsg || defaultMsg;
  }
  return defaultMsg || resMsg;
}

export function handleResponse(res, option) {
  res = Object.assign({}, res);
  option = Object.assign({}, BASE_OPTION, option);
  if (config.isResponseSuccess(res)) {
    const msg = getMsg(option.useResMsg, res.msg, option.okMsg);
    if (option.silent !== true && msg) {
      config.handleSuccessMessage({ content: msg, key: config.messageKey });
    }
    if (typeof option.onOk === 'function') {
      return option.onOk(res);
    }
  } else {
    const msg = getMsg(option.useResMsg, res.msg, option.errMsg);
    if (option.silent !== true && msg) {
      config.handleErrorMessage({ content: msg, key: config.messageKey });
    }
    if (typeof option.onFail === 'function') {
      return option.onFail(res);
    }
  }
}

export function handleFormResult(res, option = {}) {
  option = Object.assign({ silent: false }, FORM_OPTION, option);
  option.okMsg = option.baseText + option.okText;
  option.errMsg = option.baseText + option.failText;
  option.handleOk = option.onOk;
  option.handleFail = option.onFail;
  option.onOk = (res) => {
    const ok = typeof option.handleOk === 'function' ? option.handleOk(res) : true;
    return typeof ok === 'boolean' ? ok : true;
  };
  option.onFail = (res) => {
    const ok = typeof option.handleFail === 'function' ? option.handleFail(res) : false;
    return typeof ok === 'boolean' ? ok : false;
  };
  return handleResponse(res, option);
}

export function handleTableResult(res, option = {}) {
  option = Object.assign({ silent: true }, TABLE_OPTION, option);
  option.handleOk = option.onOk;
  option.handleFail = option.onFail;
  option.onOk = (res) => {
    if (typeof option.handleOk === 'function') {
      option.handleOk(res);
    }
    const data = tryToParseJson(get(res, option.dataKey), option.defaultValue);
    const total = get(res, option.totalKey) || 0;
    const page = get(res, option.pageKey) || 1;
    const pageSize = get(res, option.pageSizeKey) || 10;
    return { data, total, page, pageSize };
  };
  option.onFail = (res) => {
    if (typeof option.handleFail === 'function') {
      option.handleFail(res);
    }
    return { data: option.defaultValue, page: 1, total: 0 };
  };
  return handleResponse(res, option);
}

export function handleCommonResult(res, option = {}) {
  option = Object.assign({ silent: true }, COMMON_OPTION, option);
  option.handleOk = option.onOk;
  option.handleFail = option.onFail;
  option.onOk = (res) => {
    if (typeof option.handleOk === 'function') {
      option.handleOk(res);
    }
    return tryToParseJson(get(res, option.dataKey), option.defaultValue);
  };
  option.onFail = (res) => {
    if (typeof option.handleFail === 'function') {
      option.handleFail(res);
    }
    return option.defaultValue;
  };
  return handleResponse(res, option);
}

/*
 * async handler
 * */

async function fetchRes(api, params) {
  try {
    let res = await (typeof api === 'function' ? api(params) : api);
    return res || {};
  } catch (e) {
    console.log(e);
    return { code: 400, msg: '请求错误,请稍后再尝试!' };
  }
}

export async function handleFormRes(api, params, option = {}) {
  const res = await fetchRes(api, params);
  return handleFormResult(res, option);
}

export async function handleTableRes(api, params, option = {}) {
  const res = await fetchRes(api, params);
  return handleTableResult(res, option);
}

export async function handleCommonRes(api, params, option = {}) {
  const res = await fetchRes(api, params);
  return handleCommonResult(res, option);
}

export default {
  install(app) {
    app.config.globalProperties.handleFormRes = handleFormRes;
    app.config.globalProperties.handleTableRes = handleTableRes;
    app.config.globalProperties.handleCommonRes = handleCommonRes;
    app.config.globalProperties.handleFormResult = handleFormResult;
    app.config.globalProperties.handleTableResult = handleTableResult;
    app.config.globalProperties.handleCommonResult = handleCommonResult;
  },
};
